package com.bw;

import com.alibaba.alink.operator.batch.BatchOperator;
import com.alibaba.alink.operator.batch.dataproc.SplitBatchOp;
import com.alibaba.alink.operator.batch.dataproc.vector.VectorAssemblerBatchOp;
import com.alibaba.alink.operator.batch.evaluation.EvalClusterBatchOp;
import com.alibaba.alink.operator.batch.evaluation.EvalMultiClassBatchOp;
import com.alibaba.alink.operator.batch.source.CsvSourceBatchOp;
import com.alibaba.alink.operator.common.evaluation.ClusterMetrics;
import com.alibaba.alink.operator.common.evaluation.MultiClassMetrics;
import com.alibaba.alink.pipeline.PipelineModel;
import com.alibaba.alink.pipeline.classification.KnnClassifier;
import com.alibaba.alink.pipeline.classification.RandomForestClassifier;
import com.alibaba.alink.pipeline.clustering.KMeans;
import com.alibaba.alink.pipeline.tuning.*;

public class Test1 {
    public static void main(String[] args) throws Exception {

        BatchOperator.setParallelism(1);

        String schemaStr="label int,feature1 double,feature2 double,feature3 double,feature4 double," +
                "feature5 double,feature6 double,feature7 double,feature8 double,feature9 double," +
                "feature10 double,feature11 double,feature12 double,feature13 double";

        CsvSourceBatchOp source = new CsvSourceBatchOp()
                .setFilePath("datafile/wine.data")
                .setSchemaStr(schemaStr)
                .setFieldDelimiter(",").print();


        //6:2:2
        BatchOperator<?> trainData=new SplitBatchOp().setFraction(0.6).linkFrom(source);


        // 在训练集的平分那4分
        BatchOperator<?> middleData=trainData.getSideOutput(0);// 0.4

        // 验证数据集
        BatchOperator<?> validateData=new SplitBatchOp().setFraction(0.5).linkFrom(middleData);

        // 测试集
        BatchOperator<?> testData=validateData.getSideOutput(0);

        System.out.println("trainData:"+trainData.count());
        System.out.println("validateData:"+validateData.count());
        System.out.println("testData:"+testData.count());

        // 创建模型
        // KNN
        String [] feature=new String[]{"feature1","feature2","feature3","feature4","feature5",
                "feature6","feature7","feature8","feature9","feature10",
                "feature11","feature12","feature13"};

        String label="label";
        KnnClassifier knn = new KnnClassifier()
                .setFeatureCols(feature)
                .setPredictionCol("pred")
                .setPredictionDetailCol("pred_detail")
                .setLabelCol(label)
                .setK(3);

        BatchOperator<?> result = knn.fit(trainData).transform(validateData);
        result.print();
        // 随机森林
        RandomForestClassifier randomForestClassifier = new RandomForestClassifier()
                .setPredictionDetailCol("pred_detail")
                .setPredictionCol("pred")
                .setLabelCol(label)
                .setFeatureCols(feature);

        BatchOperator<?> result1 = randomForestClassifier
                .fit(trainData)
                .transform(validateData);
        result1.print();

        // 评估KNN
        MultiClassMetrics metrics = new EvalMultiClassBatchOp().setLabelCol("label").setPredictionDetailCol(
                "pred_detail").linkFrom(result).collectMetrics();
        System.out.println("Prefix0 accuracy:" + metrics.getAccuracy());
        System.out.println("Prefix1 recall:" + metrics.getRecall("1"));
        System.out.println("Macro Precision:" + metrics.getMacroPrecision());
        System.out.println("Micro Recall:" + metrics.getMicroRecall());
        System.out.println("Weighted Sensitivity:" + metrics.getWeightedSensitivity());


        // 评估随机森林
        MultiClassMetrics metrics1 = new EvalMultiClassBatchOp().setLabelCol("label").setPredictionDetailCol(
                "pred_detail").linkFrom(result).collectMetrics();
        System.out.println("Prefix0 accuracy:" + metrics1.getAccuracy());
        System.out.println("Prefix1 recall:" + metrics1.getRecall("1"));
        System.out.println("Macro Precision:" + metrics1.getMacroPrecision());
        System.out.println("Micro Recall:" + metrics1.getMicroRecall());
        System.out.println("Weighted Sensitivity:" + metrics1.getWeightedSensitivity());


//        BinaryClassificationTuningEvaluator tuningEvaluator = new BinaryClassificationTuningEvaluator()
//                .setLabelCol(label)
//                .setPredictionDetailCol("pred_detail")
//                .setTuningBinaryClassMetric("AUC");

        // 多分类
        MultiClassClassificationTuningEvaluator tuningEvaluator1 = new MultiClassClassificationTuningEvaluator()
                .setLabelCol("label")
                .setPredictionDetailCol("pred_detail")
                .setTuningMultiClassMetric("ACCURACY");


        // 对KNN进行调优
        ParamGrid paramGrid = new ParamGrid()
                .addGrid(knn,KnnClassifier.K, new Integer[]{3,7})
                .addGrid(knn,KnnClassifier.NUM_THREADS,new Integer[]{1,2});

        GridSearchCV cv = new GridSearchCV()
                .setEstimator(knn)
                .setParamGrid(paramGrid)
                .setTuningEvaluator(tuningEvaluator1)
                .setNumFolds(2)
                .enableLazyPrintTrainInfo("TrainInfo");
        GridSearchCVModel model = cv.fit(trainData);
        PipelineModel bestPipelineModel = model.getBestPipelineModel();





        // 对随机森林调优
        ParamGrid rt_paramGrid = new ParamGrid()
                .addGrid(randomForestClassifier,RandomForestClassifier.MAX_DEPTH, new Integer[]{20,80})
                .addGrid(randomForestClassifier,RandomForestClassifier.MAX_LEAVES,new Integer[]{10,20});
        GridSearchCV rt_cv = new GridSearchCV()
                .setEstimator(randomForestClassifier)
                .setParamGrid(rt_paramGrid)
                .setTuningEvaluator(tuningEvaluator1)
                .setNumFolds(2)
                .enableLazyPrintTrainInfo();
        GridSearchCVModel rt_cv_model=rt_cv.fit(trainData);
        PipelineModel bestPipelineModel1=rt_cv_model.getBestPipelineModel();

        // 使用两个最佳模型进行预测
        BatchOperator<?> knn_best_result=bestPipelineModel.transform(testData);
        knn_best_result.print();
        BatchOperator<?> rf_best_result = bestPipelineModel1.transform(testData);
        rf_best_result.print();

        // 最佳KNN评估
        MultiClassMetrics metrics2 = new EvalMultiClassBatchOp().setLabelCol("label").setPredictionDetailCol(
                "pred_detail").linkFrom(knn_best_result).collectMetrics();
        System.out.println("Prefix0 accuracy:" + metrics2.getAccuracy());
        System.out.println("Prefix1 recall:" + metrics2.getRecall("1"));
        System.out.println("Macro Precision:" + metrics2.getMacroPrecision());
        System.out.println("Micro Recall:" + metrics2.getMicroRecall());
        System.out.println("Weighted Sensitivity:" + metrics2.getWeightedSensitivity());

        // 最佳随机随机评估
        MultiClassMetrics metrics3 = new EvalMultiClassBatchOp().setLabelCol("label").setPredictionDetailCol(
                "pred_detail").linkFrom(rf_best_result).collectMetrics();
        System.out.println("Prefix0 accuracy:" + metrics3.getAccuracy());
        System.out.println("Prefix1 recall:" + metrics3.getRecall("1"));
        System.out.println("Macro Precision:" + metrics3.getMacroPrecision());
        System.out.println("Micro Recall:" + metrics3.getMicroRecall());
        System.out.println("Weighted Sensitivity:" + metrics3.getWeightedSensitivity());

        // K-Means
        // 向量聚合
        BatchOperator<?> vecData=new VectorAssemblerBatchOp()
                .setSelectedCols(feature)
                .setOutputCol("vec")
                .linkFrom(source);

        KMeans kmeans = new KMeans()
                .setVectorCol("vec")
                .setK(3)
                .setPredictionCol("pred");
        // 预测结果
        BatchOperator<?> kmeans_result =kmeans.fit(vecData).transform(vecData);


        ClusterMetrics kmeans_metrics = new EvalClusterBatchOp()
                .setVectorCol("vec").setPredictionCol("pred")
                .linkFrom(kmeans_result)
                .collectMetrics();
        System.out.println("CH:" + kmeans_metrics.getVrc());



    }
}
